import { AppDataSource } from "@/config/database";
import { EnabledStatusEnum, User } from "@/entities/system/user.entity";
import { ErrorHandler } from "@/middlewares/error.middleware";
import { Context } from "koa";
import * as CryptoJS from 'crypto-js';

export interface IUpdateUserParams {
    /** 用户ID */
    id: string;
}

export interface IUpdateUserBody {
    /** 用户昵称 */
    nickname?: string;
    /** 用户邮箱 */
    email?: string;
    /** 用户手机号 */
    phone?: string;
    /** 备注信息 */
    remarks?: string;
    /** 启用状态 */
    enabledStatus?: EnabledStatusEnum;
    /** 新密码（可选） */
    password?: string;
}

/** 修改用户信息 */
export async function updateUser(ctx: Context) {
    const { id } = ctx.params as IUpdateUserParams;
    const updateData = ctx.request.body as IUpdateUserBody;

    validateParams(id, updateData); // 校验参数
    const user = await checkUserExists(id); // 检查用户是否存在
    await validateUniqueFields(id, updateData); // 校验唯一性字段
    const updatedUser = await updateUserData(user, updateData); // 更新用户信息

    ctx.status = 200;
    ctx.body = {
        id: updatedUser.id,
        username: updatedUser.username,
        nickname: updatedUser.nickname,
        email: updatedUser.email,
        phone: updatedUser.phone,
        enabledStatus: updatedUser.enabledStatus,
        remarks: updatedUser.remarks,
        updatedAt: updatedUser.updatedAt
    };
}

/** 校验参数 */
const validateParams = (id: string, updateData: IUpdateUserBody) => {
    if (!id) {
        throw new ErrorHandler('用户ID不能为空', 400);
    }

    // UUID格式验证
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
    if (!uuidRegex.test(id)) {
        throw new ErrorHandler('用户ID格式不正确', 400);
    }

    // 检查是否有要更新的字段
    const hasValidField = Object.keys(updateData).some(key =>
        updateData[key as keyof IUpdateUserBody] !== undefined &&
        updateData[key as keyof IUpdateUserBody] !== null &&
        updateData[key as keyof IUpdateUserBody] !== ''
    );

    if (!hasValidField) {
        throw new ErrorHandler('请提供要更新的字段', 400);
    }

    // 验证邮箱格式
    if (updateData.email) {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (!emailRegex.test(updateData.email)) {
            throw new ErrorHandler('邮箱格式不正确', 400);
        }
    }

    // 验证密码强度
    if (updateData.password && updateData.password.length < 6) {
        throw new ErrorHandler('密码长度不能少于6位', 400);
    }

    // 验证启用状态
    if (updateData.enabledStatus && !['1', '2'].includes(updateData.enabledStatus)) {
        throw new ErrorHandler('启用状态值不正确', 400);
    }
}

/** 检查用户是否存在 */
const checkUserExists = async (id: string): Promise<User> => {
    const userRepository = AppDataSource.getRepository(User);
    const user = await userRepository.findOne({
        where: { id }
    });

    if (!user) {
        throw new ErrorHandler('用户不存在', 404);
    }

    return user;
}

/** 校验唯一性字段 */
const validateUniqueFields = async (id: string, updateData: IUpdateUserBody) => {
    const userRepository = AppDataSource.getRepository(User);

    // 检查邮箱是否已被其他用户使用
    if (updateData.email) {
        const existingEmail = await userRepository.findOne({
            where: { email: updateData.email }
        });

        if (existingEmail && existingEmail.id !== id) {
            throw new ErrorHandler('邮箱已被其他用户使用', 409);
        }
    }

    // 检查手机号是否已被其他用户使用
    if (updateData.phone) {
        const existingPhone = await userRepository.findOne({
            where: { phone: updateData.phone }
        });

        if (existingPhone && existingPhone.id !== id) {
            throw new ErrorHandler('手机号已被其他用户使用', 409);
        }
    }

    // 检查昵称是否已被其他用户使用
    if (updateData.nickname) {
        const existingNickname = await userRepository.findOne({
            where: { nickname: updateData.nickname }
        });

        if (existingNickname && existingNickname.id !== id) {
            throw new ErrorHandler('昵称已被其他用户使用', 409);
        }
    }
}

/** 更新用户信息 */
const updateUserData = async (user: User, updateData: IUpdateUserBody): Promise<User> => {
    const userRepository = AppDataSource.getRepository(User);

    // 更新字段
    if (updateData.nickname) {
        user.nickname = updateData.nickname;
    }

    if (updateData.email) {
        user.email = updateData.email;
    }

    if (updateData.phone) {
        user.phone = updateData.phone;
    }

    if (updateData.remarks !== undefined) {
        user.remarks = updateData.remarks;
    }

    if (updateData.enabledStatus) {
        user.enabledStatus = updateData.enabledStatus as any;
    }

    if (updateData.password) {
        user.password = CryptoJS.MD5(updateData.password).toString();
    }

    // 保存更新
    return await userRepository.save(user);
}
